//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <ddk.h>
#include "keypad.h"
#include <vkey.h>
#include <zenr_api.h>

//unsigned int press_count = 0;
//unsigned int release_count = 0;
#ifdef _DEBUG
static Int32 s_LastKey = 0;
#endif

Boolean PoGetIsSleeped ();

#define NU_VK_PHONE_HANG_UP             0x00
#define NU_VK_PHONE_CALL                0x01
#define NU_VK_HOME                      0x10
#define NU_VK_CAMERA                    0x20
#define NU_VK_VOLUME_UP                 0x30
#define NU_VK_VOLUME_DOWN               0x40
#define NU_VK_Power                     0x50
#define NU_VK_Lock                      0x53
#define NU_VK_LINECONTROL               0x88
#define REPEAT_INDEX                    9       // the last timer
#define VOLUME_UP_REPEAT_INDEX          9       // the last two timer
#define VOLUME_DOWN_REPEAT_INDEX        10

#define INVALID_INDEX                   0xFFFF
#define INVALID_KEYCODE                 0xCCCC

void CDECL TimerRoutine(void * pvParameter);
void CDECL TimerRepeatRoutine(void * pvParameter);
extern "C" int GetIndexFromRepeatKeyCode(unsigned long keycode);
unsigned long PoGetLcdPowerMode();
extern Bool32 g_allDevicesDown;
Boolean PoGetLcdLockScreen();
extern Bool32 g_sleeped;
extern Boolean PoGetLCDBlackWithoutLock();
extern Boolean IsLcdBlack();
extern Int32 g_Debug;
#ifdef _DEBUG
extern IDeviceDriver  *g_pDebugInfo;
#endif

int g_KeyCode[] = {
    0x00,                   //NU_VK_HANGUP
    0x01,                   //NU_VK_CALL
    0x10,                   //NU_VK_OK
    0x20,                   //NU_VK_CAMERA
    0x30,                   //NU_VK_VOLUMEUP
    0x40,                   //NU_VK_VOLUMEDOWN
    0x50,                   //NU_VK_POWER
    0x53,                   //NU_VK_Lock
    0x88,                   //NU_VK_LINECONTROL
};

unsigned long  g_RepeatKeyCode[] = {
    0x30,
    0x40,
};

CKeypad *g_pKeypad = NULL;

static int g_timetick[TOTALKEYNUMBER] = {
    100,            //1 seconds
    100,            //1 seconds
    100,            //1 seconds
    100,            //1 seconds
    100,            //1 seconds
    100,            //1 seconds
    100,            //1 seconds
    100,            //1 seconds
    100,            //1 seconds
    100,            //for repeat
};

static int GetBitNumberFromKeycode(unsigned long keycode)
{
    int index = INVALID_INDEX;

//    kprintf("keycode is %d\n", keycode, __FILE__, __LINE__);

    switch (keycode)
    {
        case NU_VK_PHONE_HANG_UP:
            index = 0;
            break;
        case NU_VK_PHONE_CALL:
            index = 1;
            break;
        case NU_VK_HOME:
            index = 2;
            break;
        case NU_VK_CAMERA:
            index = 3;
            break;
        case NU_VK_VOLUME_UP:
            index = 4;
            break;
        case NU_VK_VOLUME_DOWN:
            index = 5;
            break;
        case NU_VK_Lock:
            index = 6;
            break;
        case NU_VK_Power:
            index = 7;
            break;
        case NU_VK_LINECONTROL:
            index = 8;
            break;
        default:
            assert(0);
            break;
    }

    return index;
}

extern "C" void KeypadPressCallBack(unsigned char act_key)
{
//    char buf[80] = {0};
//   nu_puts("PressCallBack!\n");
//    nu_puts("PressCallBack=%x!\n",act_key);
#ifdef _DEBUG
    //kprintf("the s_LastKey is %x\n", s_LastKey);

    if (s_LastKey == 0x30 && act_key == 0x50) {
        nu_puts("Compounding Key!\n");
        if (g_pDebugInfo) {
            g_pDebugInfo->Control(0, NULL_MEMORYBUF, NULL, NULL);
        }
    }

    if (s_LastKey == 0x50 && act_key == 0x10) {
        g_Debug = 1;
    }
    s_LastKey = act_key;
#endif

    //unsigned char bitn = nu_KeypadCheckState();
    Int32 KeyNum;
    //press_count ++;

    //kprintf("PressCallBack:bitn=%x,act_key=%x!\n", bitn, act_key);
//    PrintDynamicPoolInfo();
//    Uint32 uFlags = SaveFlagsAndCli();

    if (!g_pKeypad->m_bRead) {
//        RestoreIF(uFlags);
        return;
    }
    if (IsLcdBlack() && !PoGetLCDBlackWithoutLock()) {
        if (0x53 != act_key && 0x00 != act_key && 0x01 != act_key && 0x10 != act_key) {
            //nu_puts("return from PressCallBack!\n");
            return;
        }
    }

    if ((act_key != NU_VK_PHONE_HANG_UP) && (act_key != NU_VK_PHONE_CALL) && (act_key != NU_VK_HOME)
         && (act_key != NU_VK_CAMERA) && (act_key != NU_VK_VOLUME_UP) && (act_key != NU_VK_VOLUME_DOWN)
         && (act_key != NU_VK_Lock) && (act_key != NU_VK_Power) && (act_key != NU_VK_LINECONTROL)) {
        return;
    }
    KeyNum = g_pKeypad->m_keyRIndex - g_pKeypad->m_keyIndex;
    if ((1 != KeyNum) && -(BUFFERSIZE-1) != KeyNum) {
        g_pKeypad->m_pNuKeyData[g_pKeypad->m_keyIndex].event_id = 1; //Press
        g_pKeypad->m_pNuKeyData[g_pKeypad->m_keyIndex].keycode = (unsigned long)(0x000000FF & act_key);
        g_pKeypad->m_keyIndex++;

        g_pKeypad->m_keyIndex = g_pKeypad->m_keyIndex % BUFFERSIZE;
    }
//    if (g_pKeypad->m_keyIndex == BUFFERSIZE) {
//        g_pKeypad->m_keyIndex = BUFFERSIZE - 1;
//    }
//    RestoreIF(uFlags);
    nu_notifyDeviceCaller((Int32)&(g_pKeypad->m_event), SIGNALED);
}

extern "C" void KeypadReleaseCallBack(unsigned char act_key)
{
//    char buf[80];
//    nu_puts("KeypadReleaseCallBack\n");
//    nu_puts("KeypadReleaseCallBack=%x!\n",act_key);
    //unsigned char bitn = nu_KeypadCheckState();
    Int32 KeyNum;
    //release_count ++;

    //if (bitn & 0x40) {
        //kprintf("Total:press_count=%d,release_count=%d!\n", press_count, release_count);
    //}
    //kprintf("ReleaseCallBack:bitn=%x,act_key=%x!\n", bitn, act_key);
//    nu_puts("RleaseCallBack!\n");
//    Uint32 uFlags = SaveFlagsAndCli();

    if (!g_pKeypad->m_bRead) {
//      RestoreIF(uFlags);
        return;
    }
    if (IsLcdBlack() && !PoGetLCDBlackWithoutLock()) {
        if (0x53 != act_key && 0x00 != act_key && 0x01 != act_key && 0x10 != act_key) {
            return ;
        }
    }
    if ((act_key != NU_VK_PHONE_HANG_UP) && (act_key != NU_VK_PHONE_CALL) && (act_key != NU_VK_HOME)
         && (act_key != NU_VK_CAMERA) && (act_key != NU_VK_VOLUME_UP) && (act_key != NU_VK_VOLUME_DOWN)
         && (act_key != NU_VK_Lock) && (act_key != NU_VK_Power) && (act_key != NU_VK_LINECONTROL)) {
        return;
    }
    if (g_pKeypad->m_bRepeat &&
        g_pKeypad->IsRepeatKeyCode((unsigned long)(0x000000FF & act_key))) {
        if (GetIndexFromRepeatKeyCode((unsigned long)(0x000000FF & act_key))
            == g_pKeypad->m_nRepeatIndex) {
            //nu_puts("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");
            g_pKeypad->m_bRepeat = FALSE;
            g_pKeypad->m_nRepeatIndex = INVALID_INDEX;
        }
    }
    KeyNum = g_pKeypad->m_keyRIndex - g_pKeypad->m_keyIndex;
    if ((1 != KeyNum) && -(BUFFERSIZE-1) != KeyNum) {
        g_pKeypad->m_pNuKeyData[g_pKeypad->m_keyIndex].event_id = 0; //Release Status
        g_pKeypad->m_pNuKeyData[g_pKeypad->m_keyIndex].keycode = (unsigned long)(0x000000FF & act_key);;
        g_pKeypad->m_keyIndex++;

        g_pKeypad->m_keyIndex = g_pKeypad->m_keyIndex % BUFFERSIZE;
    }

//    if (g_pKeypad->m_keyIndex == BUFFERSIZE) {
//        g_pKeypad->m_keyIndex = BUFFERSIZE - 1;
//    }
//    RestoreIF(uFlags);
    nu_notifyDeviceCaller((Int32)(Int32)&(g_pKeypad->m_event), SIGNALED);
}

extern "C" void KeypadPushCallback(unsigned long keycode, int *pbPushMap)
{
    //Uint32 uFlags = SaveFlagsAndCli();
    Int32 KeyNum;
    Uint32 uFlags;
    unsigned char index = (unsigned char)GetBitNumberFromKeycode(keycode);
    unsigned char bitn = zapi_HMI->KeypadCheckstate();
    //WaitResult wr;
    //if (bitn & 0x40) {
    //    kprintf("Total:press_count=%d,release_count=%d!\n", press_count, release_count);
    //}

    //kprintf("KeypadPushCallback:bitn=%x,keycode=%x,index=%x!\n", bitn, keycode, index);
//    if ((!g_pKeypad->m_bRead) || (!(bitn & (1 << index)))) {
//      RestoreIF(uFlags);
//      return;
//  }
    if (!g_pKeypad->m_bRead) {
        //RestoreIF(uFlags);
        return;
    }
    if ((index != 7) && (index != 8) && (!(bitn & (1 << index)))) {
        //RestoreIF(uFlags);
        return;
    }

    //g_pKeypad->m_mutex.Lock(&wr);
    uFlags = SaveFlagsAndCli();
    KeyNum = g_pKeypad->m_keyRIndex - g_pKeypad->m_keyIndex;
    if ((1 != KeyNum) && -(BUFFERSIZE - 1) != KeyNum) {
        g_pKeypad->m_pNuKeyData[g_pKeypad->m_keyIndex].event_id = 0x10; //Push
        g_pKeypad->m_pNuKeyData[g_pKeypad->m_keyIndex].keycode = (unsigned long)keycode;
        g_pKeypad->m_keyIndex++;

        g_pKeypad->m_keyIndex = g_pKeypad->m_keyIndex % BUFFERSIZE;
    }

//    if (g_pKeypad->m_keyIndex == BUFFERSIZE) {
//        g_pKeypad->m_keyIndex = BUFFERSIZE - 1;
//    }

    RestoreIF(uFlags);
    g_pKeypad->SetPushMap(keycode, pbPushMap);
    //g_pKeypad->m_mutex.Unlock();
    //RestoreIF(uFlags);

    nu_notifyDeviceCaller((Int32)(Int32)&(g_pKeypad->m_event), SIGNALED);
}


extern "C" void KeypadRepeatCallback(unsigned long keycode)
{
    //kprintf("keycode is %x, %s, %d\n", keycode, __FILE__, __LINE__);
    //Uint32 uFlags = SaveFlagsAndCli();
    Int32 KeyNum;
    Uint32 uFlags;
    unsigned char index = (unsigned char)GetBitNumberFromKeycode(keycode);
    unsigned char bitn = zapi_HMI->KeypadCheckstate();
    //WaitResult wr;
    //kprintf("KeypadRepeatCallback:bitn=%x,keycode=%x,index=%x!\n", bitn, keycode, index);
    //if (!g_pKeypad->m_bRead) {
    if ((!g_pKeypad->m_bRead) || (!(bitn & (1 << index)))) {
        //RestoreIF(uFlags);
        return;
    }

    //g_pKeypad->m_mutex.Lock(&wr);
    uFlags = SaveFlagsAndCli();
    KeyNum = g_pKeypad->m_keyRIndex - g_pKeypad->m_keyIndex;
    if ((1 != KeyNum) && -(BUFFERSIZE - 1) != KeyNum) {
        g_pKeypad->m_pNuKeyData[g_pKeypad->m_keyIndex].event_id = 0x1; //press
        g_pKeypad->m_pNuKeyData[g_pKeypad->m_keyIndex].keycode = (unsigned long)0xFFFFFF00 | keycode;;

        g_pKeypad->m_keyIndex++;

        g_pKeypad->m_keyIndex = g_pKeypad->m_keyIndex % BUFFERSIZE;
    }

//    if (g_pKeypad->m_keyIndex == BUFFERSIZE) {
//        g_pKeypad->m_keyIndex = BUFFERSIZE - 1;
//    }
    //g_pKeypad->m_mutex.Unlock();
    //RestoreIF(uFlags);
    RestoreIF(uFlags);

    nu_notifyDeviceCaller((Int32)(Int32)&(g_pKeypad->m_event), SIGNALED);
}

int GetIndexFromKeyCode(unsigned long keycode);
int GetVkeyFromNuVk(int nu_keycode);
//int m_pushUp = 0;  //0~6 bit

CKeypad::CKeypad()
{
    m_head = 0;
    m_tail = 0;

    m_pushUp = 0;
    m_bRepeat = FALSE;
    m_nRepeatIndex = INVALID_INDEX;

    m_keyIndex = 0;
    m_keyRIndex = 0;
    m_bRead = FALSE;

    for(int i = 0; i < TOTALKEYNUMBER; i++) {
        m_pTimers[i] = NULL;
    }

    memset(m_pNuKeyData, 0, sizeof(KPD_DATA) * BUFFERSIZE);
}


void InputNotifyByIsr(int eType, int nCode, void *pParam)
{
    unsigned long premode=PoGetLcdPowerMode();
    if(premode==6/*Invalid powermode*/) return;

    if (premode<=1/*LCM black*/
        && PoGetLcdLockScreen()
        && (nCode == 0x10 || nCode == 0x20)) {//Locked
        //cwrite('~');
        return;//ignore touch & key input when lockscreen
    }

    NotifyByIsr(EVENT_INPUT, nCode, pParam);//notify power manager an input occur.

    if(premode<=1/*Power_Suspend*/
        && !(nCode&0x40)) {
        //cwrite('~');
        return;//if lcd power off,ignore common input.
    }

    //SoundNotify(eType, nCode, pParam);
    //if (TRUE == CheckIfSoftUnlock(eType, nCode, pParam)) return;//Stop '*'
    //NotifyByIsr(eType, nCode, pParam);
}

ECode CKeypad::Read(
    /* [in] */ Int64 offset,
    /* [in] */ Int32 bytesToRead,
    /* [out] */ MemoryBuf* pBuffer,
    /* [out] */ IEvent** ppCompletionEvent)
{
    KPD_DATA* buf = (KPD_DATA *)pBuffer->GetPayload();
    Boolean bHavePush;
    Int32 index;
    Int32 KeyNum;
    //WaitResult wr;
    if (!m_bRead) m_bRead = TRUE;

    if (m_head == m_tail) {
LOOP:
        //kprintf("Wait Event:m_keyIndex=%d!\n", m_keyIndex);
        WaitResult wr;
        EventState state;
        m_event.Wait(&wr, &state);
        if (WaitResult_Interrupted == wr) {
            return NOERROR;
        }
    }

    KeyNum = m_keyIndex;
    KeyNum = (KeyNum >= m_keyRIndex)? (KeyNum - m_keyRIndex) : (BUFFERSIZE - m_keyRIndex + KeyNum);
    if (KeyNum) {
        assert(KeyNum > 0 && KeyNum < BUFFERSIZE);
        int i = m_keyRIndex;
        for (int j = 0; j < KeyNum; j++) {
            if (!m_bRepeat || m_nRepeatIndex == INVALID_INDEX) {
                if (m_pTimers[REPEAT_INDEX] != NULL) {
                    m_pTimers[REPEAT_INDEX]->Cancel();
                    delete m_pTimers[REPEAT_INDEX];
                    m_pTimers[REPEAT_INDEX] = NULL;
                }
            }
            if (0x01 == m_pNuKeyData[i].event_id) {
                //Repeat Keycode
                if (IsRepeatKeyCode(m_pNuKeyData[i].keycode) && m_bRepeat) {
                    if (GetIndexFromRepeatKeyCode(m_pNuKeyData[i].keycode)
                        == m_nRepeatIndex) {
                        if (m_pTimers[REPEAT_INDEX] != NULL) {
                            m_pTimers[REPEAT_INDEX]->Cancel();
                            m_pTimers[REPEAT_INDEX]->Set(g_timetick[REPEAT_INDEX]);
                            m_pTimers[REPEAT_INDEX]->Start();
                        }
                    }
                }

//                if ((m_pNuKeyData[i].keycode & 0xFFFFFF00) != 0) {
//
//                }
                index = GetIndexFromKeyCode(0x000000FF & m_pNuKeyData[i].keycode);
                assert(index >= 0 && index < 9);

                if (!(IsRepeatKeyCode(m_pNuKeyData[i].keycode) && m_bRepeat &&
                        GetIndexFromRepeatKeyCode(m_pNuKeyData[i].keycode)
                        == m_nRepeatIndex) &&
                       (m_pNuKeyData[i].keycode & 0xFFFFFF00) == 0) {
                       //  || (m_pNuKeyData[i].keycode & 0xFFFFFF00) != 0
//                        kprintf("%s, %d\, keycode is %xn", __FILE__, __LINE__, m_pNuKeyData[i].keycode);

                        m_pTimers[index] = new DzTimer(g_timetick[index], TimerRoutine, (void *)g_KeyCode[index]);
                        if (m_pTimers[index]) {
                            m_pTimers[index]->Start();
                        }
                }

                m_buffer[m_head].event_id = 0x80000000;
//                kprintf("Down Message, %x \n", m_buffer[m_head].event_id);
                if ((m_pNuKeyData[i].keycode & 0xFFFFFF00) != 0xFFFFFF00) {
                    m_buffer[m_head].keycode = GetVkeyFromNuVk(m_pNuKeyData[i].keycode);
                } else {
                    m_buffer[m_head].keycode = GetVkeyFromNuVk( 0x000000FF & m_pNuKeyData[i].keycode);
                }

                m_head = (m_head + 1) % BUFFERSIZE;
//POWER:
//                ;
            } else if (0 == m_pNuKeyData[i].event_id) {
                //release status
                IsPushUp(m_pNuKeyData[i].keycode, &bHavePush);
                index = GetIndexFromKeyCode(m_pNuKeyData[i].keycode);
                assert(index >= 0 && index < 9);

                if (bHavePush) {
                    //push up
                    m_buffer[m_head].event_id = 0x00000001;
                } else {
                    if (m_pTimers[index] != NULL) {
                        m_pTimers[index]->Cancel();
                        delete m_pTimers[index];
                        m_pTimers[index] = NULL;
                    }
                    m_buffer[m_head].event_id = 0x0;
                }
                m_buffer[m_head].keycode = GetVkeyFromNuVk(m_pNuKeyData[i].keycode);
                m_head = (m_head + 1) % BUFFERSIZE;
            } else {
                //push
                assert(m_pNuKeyData[i].event_id == 0x10);
                //kprintf("m_bRepeat is %d, keycode is %x\n", m_bRepeat, m_pNuKeyData[i].keycode);
                if (!m_bRepeat && IsRepeatKeyCode(m_pNuKeyData[i].keycode)) {
                    m_bRepeat = TRUE;
                    m_nRepeatIndex = GetIndexFromRepeatKeyCode(m_pNuKeyData[i].keycode);
                    m_pTimers[REPEAT_INDEX] = new DzTimer(g_timetick[REPEAT_INDEX],
                    TimerRepeatRoutine, (void *)g_RepeatKeyCode[m_nRepeatIndex]);
                    if (m_pTimers[REPEAT_INDEX]) {
                        m_pTimers[REPEAT_INDEX]->Start();
                    }
                }

                m_buffer[m_head].event_id = 0x80000001;
                m_buffer[m_head].keycode = GetVkeyFromNuVk(m_pNuKeyData[i].keycode);
                //kprintf("Push, event_id %x \n", m_buffer[m_head].event_id);
                m_head = (m_head + 1) % BUFFERSIZE;
            }
            i = (i + 1) % BUFFERSIZE;
            m_keyRIndex = (m_keyRIndex + 1) % BUFFERSIZE;
        }
    }
    //kprintf("m_head=%d,m_tail=%d\n",m_head,m_tail);
    if (m_head == m_tail) {
        goto LOOP;
    }

    *buf = m_buffer[m_tail];
    m_tail = (m_tail + 1) % BUFFERSIZE;
    InputNotifyByIsr(EVENT_KEYPAD, 0x10, NULL);//NULL for temp

    return NOERROR;
}


ECode CKeypad::IsRepeatKeyCode(unsigned long keycode)
{
    keycode = 0x000000FF & keycode;
    if (g_RepeatKeyCode[0] == keycode || g_RepeatKeyCode[1] == keycode) {
        return TRUE;
    } else {
        return FALSE;
    }
}

ECode CKeypad::Control(
        /* [in] */ Handle32 controlCode,
        /* [in] */ const MemoryBuf &inBuffer,
        /* [out] */ MemoryBuf* pOutBuffer,
        /* [out] */ IEvent** ppCompletionEvent)
{
    if (!m_bRead) m_bRead = TRUE;
    //kprintf("-----------------in keypad Control controlCode = %d!\n", controlCode);
   switch (controlCode) {
#if 1
        case 0x10:
        {
            int i = 0;
            MemoryBuf_<sizeof(KPD_DATA)> outData;
            while(1) {
                kprintf("%s, %d\n", __FILE__, __LINE__);
                Read(0,0, &outData, 0);
//                DzSleep(100, NULL);
                i++;
            }
        }
        break;
#endif
        case 1000:
            //turn off keypad backlight
            zapi_HMI->KeypadLED_Off();
            break;
        case 1001:
            //turn on keypad backlight
            zapi_HMI->KeypadLED_On();
            break;
    }
    //kprintf("------------return from keypad\n");
    return NOERROR;
}

ECode CKeypad::IsPushUp(unsigned long keycode, Boolean *pbHavePush)
{
    int index;

    if (!m_pushUp) {
        *pbHavePush = FALSE;
        return NOERROR;
    }

    index = GetIndexFromKeyCode(keycode);

    if (m_pushUp & (1ul << index)) {
        *pbHavePush = TRUE;
        m_pushUp &= ~(1ul << index);
    } else {
        *pbHavePush = FALSE;
    }

    return NOERROR;
}


int CKeypad::SetPushMap(unsigned long keycode, int *pPushMap)
{
    switch (keycode) {
        case NU_VK_PHONE_HANG_UP:
            *pPushMap |= 0x01;
            break;
        case NU_VK_PHONE_CALL:
            *pPushMap |= 0x02;
            break;
        case NU_VK_HOME:
            *pPushMap |= 0x04;
            break;
        case NU_VK_CAMERA:
            *pPushMap |= 0x08;
            break;
        case NU_VK_VOLUME_UP:
            *pPushMap |= 0x10;
            break;
        case NU_VK_VOLUME_DOWN:
            *pPushMap |= 0x20;
            break;
        case NU_VK_Power:
            *pPushMap |= 0x40;
            break;
        case NU_VK_Lock:
            *pPushMap |= 0x80;
            break;
        case NU_VK_LINECONTROL:
            *pPushMap |= 0x100;
            break;
        default:
            assert(0);
            break;
    }

    return *pPushMap;
}

EXTERN IDeviceDriver * CDECL CreateKeypad(uint_t uDeviceNo, void *pvParameter)
{
    g_pKeypad = new CKeypad;
    if (!g_pKeypad) {
        DRV_EXPRESSION(ERRORLEVEL, kprintf("not enough memory\n"));
        return NULL;
    }

    zapi_HMI->AddKeypadCallback(&KeypadPressCallBack, &KeypadReleaseCallBack);

    if (!g_pKeypad->m_pNuKeyData) {
        kprintf("Init Keypad Failed!\n");
    }

    return g_pKeypad;
}


void CDECL TimerRoutine(void * pvParameter)
{
    unsigned long keycode = (int) pvParameter;

#ifdef _DEBUG
    kprintf("Key Push  %x\n", keycode);
    if (NU_VK_HOME == keycode) {
        if (g_pDebugInfo) {
            g_pDebugInfo->Control(0, NULL_MEMORYBUF, NULL, NULL);
        }
    }
#endif

    KeypadPushCallback(keycode, &g_pKeypad->m_pushUp);
}

void CDECL TimerRepeatRoutine(void * pvParameter)
{
    unsigned long keycode = (int) pvParameter;
    KeypadRepeatCallback(keycode);
}

int GetIndexFromKeyCode(unsigned long keycode)
{
    int index = INVALID_INDEX;

//    kprintf("keycode is %d\n", keycode, __FILE__, __LINE__);

    switch (keycode)
    {
        case NU_VK_PHONE_HANG_UP:
            index = 0;
            break;
        case NU_VK_PHONE_CALL:
            index = 1;
            break;
        case NU_VK_HOME:
            index = 2;
            break;
        case NU_VK_CAMERA:
            index = 3;
            break;
        case NU_VK_VOLUME_UP:
            index = 4;
            break;
        case NU_VK_VOLUME_DOWN:
            index = 5;
            break;
        case NU_VK_Power:
            index = 6;
            break;
        case NU_VK_Lock:
            index = 7;
            break;
        case NU_VK_LINECONTROL:
            index = 8;
            break;
        default:
            assert(0);
            break;
    }

    return index;
}


int GetVkeyFromNuVk(int nu_keycode)
{
    unsigned long vkeycode = INVALID_KEYCODE;
    static int s_WakeUpKeyCode = -1;
    if (IsLcdBlack()) {
        if (s_WakeUpKeyCode == nu_keycode) {
            NotifyByIsr(EVENT_INPUT, 0, NULL);
            s_WakeUpKeyCode = -1;
            return VK_WakeUp;
        }
        s_WakeUpKeyCode = nu_keycode;
        return VK_WakeUp;
    }
    switch (nu_keycode)
    {
        case NU_VK_PHONE_HANG_UP:
            vkeycode = VK_PHONE_HANG_UP;
            break;
        case NU_VK_PHONE_CALL:
            vkeycode = VK_PHONE_CALL;
            break;
        case NU_VK_HOME:
            vkeycode = VK_HOME;
            break;
        case NU_VK_CAMERA:
            vkeycode = VK_CAMERA;
            break;
        case NU_VK_VOLUME_UP:
            vkeycode = VK_VOLUME_UP;
            break;
        case NU_VK_VOLUME_DOWN:
            vkeycode = VK_VOLUME_DOWN;
            break;
        case NU_VK_Power:
            vkeycode = VK_Power;
            break;
        case NU_VK_Lock:
            NotifyByIsr(EVENT_INPUT, 0, NULL);
            vkeycode = VK_Lock;
            break;
        case NU_VK_LINECONTROL:
            vkeycode = VK_LINECONTROL;
			break;
        default:
            assert(0);
            break;
    }

    return vkeycode;
}

extern "C" int GetIndexFromRepeatKeyCode(unsigned long keycode)
{
    keycode = 0x000000FF & keycode;

    if ( g_RepeatKeyCode[0] == keycode) {
        return 0;
    } else if (g_RepeatKeyCode[1] == keycode) {
        return 1;
    } else {
        assert(0);
        return INVALID_KEYCODE;
    }
}

